package net.bithaven.roguelike.ui;

import java.awt.Font;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;

import javax.swing.JFrame;
import javax.swing.JTextArea;


public class RogueLikeUI extends JFrame implements UserInterface, WindowListener, KeyListener {
	private static final long serialVersionUID = -5407023095535297294L;
	
	private final int width;
	private final int height;
	private JTextArea area;
	protected final ReentrantLock lock;
	private static ArrayList<String> input = new ArrayList<String>();
	private boolean isNewInput;

	public RogueLikeUI (int width, int height) {
		super("RogueLike UI");
		super.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		this.width = width;
		this.height = height;
		lock = new ReentrantLock();
		isNewInput = false;

		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				start();
			}
		});
	}

	private void start () {
		area = new JTextArea(height, width);
		Font font = new Font(Font.MONOSPACED, Font.PLAIN, 12);
		area.setFont(font);
		area.setEditable(false);
		area.requestFocus();
		add(area);

		addWindowListener(this);
		area.addKeyListener(this);

		pack();

		synchronized(this) {
			notify();
		}
		
		setVisible(true);
		//setSize(new Dimension(640, 480));
		//setMaximizedBounds(env.getMaximumWindowBounds ());
		//setExtendedState(frame.getExtendedState() | frame.MAXIMIZED_BOTH);
		validate();
	}

	public void update (String stateRep) throws InterruptedException {
		while(area == null) { // Might execute before area is initialized
			synchronized(this) {
				wait();
			}
		}

		area.setText(stateRep);
	}


	/**
	 * @param args
	 * @throws InterruptedException 
	 */
	public static void main(String[] args) throws InterruptedException {
		RogueLikeUI test = new RogueLikeUI(80, 25);

		test.update("hi");

		while(!input.contains("quit") && !input.contains("q")) {
			input = test.getInput();
			// System.out.println(input); // DEBUG
		}

		// System.out.println("bubye"); // DEBUG
	}

	public void windowActivated(WindowEvent arg0) {

	}

	public void windowClosed(WindowEvent arg0) {

	}

	public synchronized void windowClosing(WindowEvent arg0) {
		lock.lock();
		if (!isNewInput) {
			input.add("quit");
			isNewInput = true;
		}
		lock.unlock();

		notify();
		
		dispose();
	}

	@Override
	public void windowDeactivated(WindowEvent e) {

	}

	@Override
	public void windowDeiconified(WindowEvent e) {

	}

	@Override
	public void windowIconified(WindowEvent e) {

	}

	@Override
	public void windowOpened(WindowEvent e) {

	}

	@Override
	public void keyPressed(KeyEvent arg0) {

	}

	@Override
	public void keyReleased(KeyEvent arg0) {

	}

	@Override
	public synchronized void keyTyped(KeyEvent e) {
		lock.lock(); 
		/* Got rid of locks because would cause game to freeze.
		 * Possibly because keyTyped is reentered every time a key is pressed, so locks itself out
		 */
		
		if (!isNewInput) {
			input.add(Character.toString(e.getKeyChar()));
			isNewInput = true;
		}
		lock.unlock();

		notify();
	}

	@SuppressWarnings("unchecked")
	public ArrayList<String> getInput() throws InterruptedException {
		ArrayList<String> out;
		
		while(area == null) { // Might execute before area is initialized
			synchronized(this) {
				wait();
			}
		}
		
		lock.lock();		
		while (!isNewInput) {
			lock.unlock();
			try {
				synchronized(this) {
					wait();
				}
			} catch (InterruptedException e) {

			}
			lock.lock();
		}
		
		out = (ArrayList<String>)input.clone();

		input.clear();

		isNewInput = false;
		
		lock.unlock();

		return out;
	}

	public void cleanup() {
		synchronized(this) {
			notifyAll();
		}
		dispose();
	}

}
